package com.mrper.filedialog.ui

import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.widget.AdapterView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import com.mrper.filedialog.R
import com.mrper.filedialog.utils.io.FileFilterFactory
import com.mrper.filedialog.utils.io.FileScannerUtils
import com.mrper.filedialog.data.adapter.BreadCrumbsAdapter
import com.mrper.filedialog.data.adapter.FileManagerAdapter
import com.mrper.filedialog.utils.io.getStoragePaths
import kotlinx.android.synthetic.main.activity_file_manager.*
import java.io.File

class FileManagerActivity : AppCompatActivity(), AdapterView.OnItemClickListener {

    companion object {

        /** 选择请求 **/
        const val CHOOSE_REQUEST = 19999

    }

    private val fileManagerAdapter by lazy { FileManagerAdapter(this) }

    private val breadCrumbsAdapter by lazy { initializerBreadCrumbsAdapter() }

    private val sdcardPaths = mutableListOf<String>()

    private val lsPositionCache = mutableMapOf<String, Int>()

    private lateinit var currentSDCardPath: String

    private var currentFolder: File? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_file_manager)
        toolbar.setNavigationOnClickListener {
            if (!isFolderCanBack()) return@setNavigationOnClickListener else finish()
        }
        lvFiles.apply {
            onItemClickListener = this@FileManagerActivity
            adapter = fileManagerAdapter
        }
        rvBreadCrumbs.apply {
            layoutManager =
                LinearLayoutManager(this@FileManagerActivity, LinearLayoutManager.HORIZONTAL, false)
            adapter = breadCrumbsAdapter
        }
        sdcardPaths.apply {
            clear()
            addAll(getStoragePaths()?.toMutableList() ?: mutableListOf())
        }
        if (!sdcardPaths.isNullOrEmpty()) {
            currentSDCardPath = sdcardPaths.first()
            currentFolder = File(currentSDCardPath)
            currentSDCardPath.listFoldersAndFiles()
        }
    }

    override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        val item = fileManagerAdapter.getItem(position) as File
        if (item.isDirectory) {
            if (!item.canRead()) {
                Toast.makeText(this, "该文件夹不可读取", Toast.LENGTH_SHORT).show()
                return
            }
            if (item.parentFile?.exists() == true)
                lsPositionCache[item.parentFile!!.absolutePath] = lvFiles.firstVisiblePosition
            currentFolder = item
            item.absolutePath.listFoldersAndFiles()
        }
        if (item.isFile) {
            setResult(Activity.RESULT_OK, Intent().apply {
                putExtra("file", item.absolutePath)
            })
            finish()
        }
    }

    override fun onBackPressed() {
        if (!isFolderCanBack()) return
        super.onBackPressed()
    }

    /** 是否是顶级目录 **/
    private fun String.isTopLevelFolder(): Boolean =
        isNullOrEmpty() || !File(this).exists() || this in sdcardPaths

    /** 是否是顶级目录 **/
    private fun File.isTopLevelFolder(): Boolean {
        if (!exists() || absolutePath.isNullOrEmpty()) return true
        return absolutePath in sdcardPaths
    }

    /** 文件夹是否支持返回 **/
    private fun isFolderCanBack(): Boolean {
        if (currentFolder?.isTopLevelFolder() != false) return true
        val pf = currentFolder?.parentFile
        if (pf?.exists() == true) {
            currentFolder = pf
            pf.absolutePath.listFoldersAndFiles()
            return false
        }
        return true
    }

    /** 执行文件搜索 **/
    private fun String.listFoldersAndFiles() = Thread {
        runOnUiThread { pbLoading.isVisible = true }
        FileScannerUtils.list(
            this,
            FileFilterFactory.getFileFilter(),
            { folders, files ->
                runOnUiThread {
                    setCurrentBreadCrumbs()
                    fileManagerAdapter.apply {
                        clear()
                        add(folders.toMutableList())
                        add(files.toMutableList())
                        notifyDataSetChanged()
                        lvFiles.setSelection(lsPositionCache[this@listFoldersAndFiles] ?: 0)
                    }
                    pbLoading.isVisible = false
                }
            }) {
            runOnUiThread {
                pbLoading.isVisible = false
            }
        }
    }.start()

    /** 设置文件夹当前的面包屑 **/
    private fun String.setCurrentBreadCrumbs() {
        val sdcardOrderIndex = sdcardPaths.indexOf(currentSDCardPath) + 1
        val deviceName = "存储设备${if (sdcardPaths.size > 1) sdcardOrderIndex.toString() else ""}"
        breadCrumbsAdapter.apply {
            clear()
            add(mapOf("text" to deviceName, "hasNavigation" to false))
            val pathParts =
                this@setCurrentBreadCrumbs.replaceFirst(Regex.fromLiteral(currentSDCardPath), "")
                    .split(File.separator).filter { v -> !TextUtils.isEmpty(v) }
            pathParts.forEach { item -> add(mapOf("text" to item, "hasNavigation" to true)) }
            notifyDataSetChanged()
        }
    }

    /** 初始化面包屑适配器 **/
    private fun initializerBreadCrumbsAdapter() = BreadCrumbsAdapter(this).apply {
        onItemClick = here@{ _, relativePath, _ ->
            if (relativePath.isEmpty()) {
                if ((currentFolder?.isTopLevelFolder() != false)) {
                    if (sdcardPaths.size <= 1) return@here
                    showSDCardChooseDialog()
                } else {
                    currentFolder = File(currentSDCardPath)
                }
            } else {
                currentFolder = File("$currentSDCardPath/$relativePath")
            }
            currentFolder?.absolutePath?.listFoldersAndFiles()
        }
    }

    /** 显示SDCard的选择对话框 **/
    private fun showSDCardChooseDialog() = AlertDialog.Builder(this)
        .setTitle("请选择存储设备")
        .setItems(mutableListOf(*sdcardPaths.toTypedArray()).mapIndexed { index, item ->
            "存储设备${index + 1}${if (item == currentSDCardPath) "(当前)" else ""}"
        }.toTypedArray()) { dialog, which ->
            currentSDCardPath = sdcardPaths[which]
            currentFolder = File(currentSDCardPath)
            currentSDCardPath.listFoldersAndFiles()
            dialog.dismiss()
        }
        .create()
        .show()

}